home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 2.toast / pc / sample code / quicktime / basics / videoframetogworld / videoframetogworld.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  11.6 KB  |  379 lines

  1. /*
  2.     File:        VideoFrameToGWorld.c
  3.     
  4.     Description: VideoFrameToGWorld is an example of decompressing frames from a video track
  5.                  into an offscreen buffer so the pixels can be manipulated at a later time.
  6.  
  7.     Author:        era based on code provided by Kevin Marks
  8.  
  9.     Copyright:     © Copyright 2000 Apple Computer, Inc. All rights reserved.
  10.     
  11.     Disclaimer:    IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
  12.                 ("Apple") in consideration of your agreement to the following terms, and your
  13.                 use, installation, modification or redistribution of this Apple software
  14.                 constitutes acceptance of these terms.  If you do not agree with these terms,
  15.                 please do not use, install, modify or redistribute this Apple software.
  16.  
  17.                 In consideration of your agreement to abide by the following terms, and subject
  18.                 to these terms, Apple grants you a personal, non-exclusive license, under Apple’s
  19.                 copyrights in this original Apple software (the "Apple Software"), to use,
  20.                 reproduce, modify and redistribute the Apple Software, with or without
  21.                 modifications, in source and/or binary forms; provided that if you redistribute
  22.                 the Apple Software in its entirety and without modifications, you must retain
  23.                 this notice and the following text and disclaimers in all such redistributions of
  24.                 the Apple Software.  Neither the name, trademarks, service marks or logos of
  25.                 Apple Computer, Inc. may be used to endorse or promote products derived from the
  26.                 Apple Software without specific prior written permission from Apple.  Except as
  27.                 expressly stated in this notice, no other rights or licenses, express or implied,
  28.                 are granted by Apple herein, including but not limited to any patent rights that
  29.                 may be infringed by your derivative works or by other works in which the Apple
  30.                 Software may be incorporated.
  31.  
  32.                 The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
  33.                 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
  34.                 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  35.                 PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
  36.                 COMBINATION WITH YOUR PRODUCTS.
  37.  
  38.                 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
  39.                 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  40.                 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  41.                 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
  42.                 OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
  43.                 (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
  44.                 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  45.                 
  46.     Change History (most recent first): <1> 4/1/00 initial release
  47.  
  48. */
  49.  
  50. #include "VideoFrameToGWorld.h"
  51.  
  52. // Globals
  53. //------------------------------------------------------------------------------
  54.     WindowRef    gWindow = NULL;
  55.     GWorldPtr    gSrcGWorld = NULL;
  56.     Movie        gMovie = NULL;
  57.     TimeValue     gMovieTime = 0;            // set current time value to begining of the Movie
  58.     UInt32        gFrameCount = -1;
  59.     UInt32        gFrameNumber = 0;
  60.     Rect         gMovieBox;
  61.  
  62. //------------------------------------------------------------------------------
  63. //    Open up the Movie file and get a Movie from it.
  64. //------------------------------------------------------------------------------
  65. void OpenMovie( void )
  66. {
  67.     FSSpec    theFSSpec;
  68.     short    refnum = 0;
  69.     OSType  openTypeList[] = {kQTFileTypeMovie};
  70.     short     numTypes = 1;
  71.     
  72.     OSErr err = noErr;
  73.  
  74.     err = GetOneFileWithPreview(numTypes, openTypeList, &theFSSpec, NULL);
  75.     BailError(err);
  76.  
  77.     // open a Movie file using the FSSpec and create a Movie from that file.    
  78.     err = OpenMovieFile(&theFSSpec, &refnum, fsRdPerm);
  79.     BailError(err);
  80.  
  81.     NewMovieFromFile(&gMovie, refnum, NULL, NULL, newMovieActive, NULL);    
  82.  
  83. bail:    
  84.     //    we're done with the file.
  85.     if (refnum)
  86.         CloseMovieFile(refnum);
  87. }
  88.  
  89. //------------------------------------------------------------------------------
  90. //    Count the number of video "frames" in the Movie by stepping through
  91. //  all of the video "interesting times", or in other words, the places where the
  92. //    movie displays a new video sample. The time between these interesting times
  93. //  is not necessarily constant.
  94. //------------------------------------------------------------------------------
  95. void CountThemFrames( void )
  96. {
  97.     OSType        whichMediaType = VIDEO_TYPE;
  98.     short        flags = nextTimeMediaSample + nextTimeEdgeOK;
  99.     TimeValue    duration;
  100.     TimeValue    theTime = 0;
  101.     
  102.     while (theTime >= 0) {
  103.         gFrameCount++;
  104.         GetMovieNextInterestingTime(gMovie,
  105.                                     flags,
  106.                                     1,
  107.                                     &whichMediaType,
  108.                                     theTime,
  109.                                     0,
  110.                                     &theTime,
  111.                                     &duration);
  112.  
  113.         //    after the first interesting time, don't include the time we
  114.         //  are currently at.
  115.  
  116.         flags = nextTimeMediaSample;
  117.     } // while
  118. }
  119.  
  120. //------------------------------------------------------------------------------
  121. //    Get the bounding rectangle of the Movie the create a 32-bit GWorld
  122. //  with those dimensions.
  123. //    This GWorld will be used for rendering Movie frames into.
  124. //------------------------------------------------------------------------------
  125. void MakeGWorld( void )
  126. {
  127.     Rect srcRect;
  128.     Rect portRect;
  129.     RGBColor theBlackColor = { 0, 0, 0 };
  130.     RGBColor theWhiteColor = { 65535, 65535, 65535 };
  131.     
  132.     OSErr err = noErr;
  133.     
  134.     GetMovieBox(gMovie,&srcRect);
  135.     
  136.     err = NewGWorld(&gSrcGWorld,
  137.                     k32ARGBPixelFormat,
  138.                     &srcRect,
  139.                     NULL,
  140.                     NULL,
  141.                     0);
  142.     BailError(err);
  143.     
  144.     LockPixels(GetGWorldPixMap(gSrcGWorld));
  145.  
  146.     SetGWorld(gSrcGWorld,NULL);
  147.     GetPortBounds(gSrcGWorld, &portRect);
  148.     RGBBackColor(&theBlackColor);
  149.     RGBForeColor(&theWhiteColor);
  150.     EraseRect(&portRect);        
  151.  
  152. bail:
  153.     return;
  154. }
  155.  
  156. //------------------------------------------------------------------------------
  157. //    Blit the contents of the GWorld to the window
  158. //------------------------------------------------------------------------------
  159. void BlitToScreen( void )
  160. {
  161.     Rect srcRect;
  162.     Rect destRect;
  163.     
  164.     GetPortBounds(gSrcGWorld, &srcRect);
  165.     GetPortBounds(GetWindowPort(gWindow), &destRect);
  166.     CopyBits(GetPortBitMapForCopyBits(gSrcGWorld),
  167.              GetPortBitMapForCopyBits(GetWindowPort(gWindow)),
  168.              &srcRect,
  169.              &destRect,
  170.              srcCopy,
  171.              NULL);
  172. }
  173.  
  174. //------------------------------------------------------------------------------
  175. //    First get the next frame of the movie, set the movie time for that frame,
  176. //  then task the movie which will draw the frame to the GWorld
  177. //  Modify the movie matrix so the next frame will be rotated just for fun and
  178. //  finally draw the frame number on top of the image and inval the window rect
  179. //------------------------------------------------------------------------------
  180. void NextFrame( void )
  181. {
  182.     CGrafPtr         savedPort;
  183.      GDHandle         savedDevice;
  184.      Rect              theRect;
  185.     char              frame[32];
  186.     Str255             theString;
  187.     Rect              invalRect;
  188.     MatrixRecord    theMovieMatrix;
  189.     
  190.     // these don't change, always rotate 30 degrees anchored in
  191.     // the center of the frame
  192.     static Fixed degrees = Long2Fix(30);
  193.     static Fixed x = Long2Fix((gMovieBox.right - gMovieBox.left) / 2);
  194.     static Fixed y = Long2Fix((gMovieBox.bottom - gMovieBox.top) / 2);
  195.     
  196.     if ( gFrameNumber < gFrameCount ) {
  197.  
  198.         TimeValue duration;
  199.         
  200.         GetGWorld(&savedPort, &savedDevice);
  201.            SetGWorld(gSrcGWorld, NULL);
  202.         
  203.         // get the next frame of the source movie
  204.         short     flags = nextTimeMediaSample;
  205.         OSType    whichMediaType = VIDEO_TYPE;
  206.  
  207.         // if this is the first frame, include the frame we are currently on
  208.         if (gFrameNumber == 0)
  209.             flags |= nextTimeEdgeOK;
  210.  
  211.         // skip to the next interesting time and get the duration for that frame
  212.         GetMovieNextInterestingTime(gMovie,
  213.                                     flags,
  214.                                     1,
  215.                                     &whichMediaType,
  216.                                     gMovieTime,
  217.                                     0,
  218.                                     &gMovieTime,
  219.                                     &duration);
  220.  
  221.         // set the time for the frame and give time to the movie toolbox
  222.         SetMovieTimeValue(gMovie,gMovieTime);
  223.         GetPortBounds(gSrcGWorld, &theRect);
  224.         EraseRect(&theRect);    // paint the background black
  225.         
  226.         // *** this does the actual drawing into the GWorld ***
  227.         MoviesTask(gMovie,0);
  228.  
  229. //------------------------------------------------------------------------------
  230. // You now have pixels you can play with in the GWorld!
  231. // This sample simply blits the contents of the GWorld back to
  232. // a window with the frame number drawn on top of the image
  233. //------------------------------------------------------------------------------
  234.         
  235.         // have some fun and rotate the movie frame
  236.         GetMovieMatrix(gMovie, &theMovieMatrix);
  237.         RotateMatrix(&theMovieMatrix, degrees, x, y);
  238.         SetMovieMatrix(gMovie, &theMovieMatrix);        
  239.  
  240.         gFrameNumber++;
  241.  
  242.         // draw the frame number on top of the image        
  243.         TextSize(12);
  244.         TextMode(srcCopy);
  245.         MoveTo( theRect.left + 5, theRect.bottom - 15 );
  246.         sprintf(frame,"Frame #%ld",gFrameNumber);
  247.         CopyCStringToPascal(frame, theString);
  248.         DrawString(theString);
  249.         
  250.         SetGWorld(savedPort, savedDevice);
  251.         
  252.         // inval the window to generate an update event
  253.         GetPort(&savedPort);
  254.         SetPortWindowPort(gWindow);
  255.         
  256.         GetWindowBounds(gWindow, kWindowContentRgn, &invalRect);
  257.         GlobalToLocal( (Point *)&invalRect.top);
  258.         InvalWindowRect(gWindow, &invalRect);
  259.         
  260.         SetPort(savedPort);
  261.         
  262.     } else {
  263.          // reset the movie time back to the beginning
  264.          // then do it all over again
  265.         gMovieTime = 0;
  266.         gFrameNumber = 0;
  267.         NextFrame();
  268.     }
  269. }
  270.  
  271. int main()
  272. {
  273.     Rect rectWnd;
  274.     Rect rectMovie;
  275.     WindowRef pWhichWindow;
  276.     short nPart;
  277.     EventRecord theEvent;
  278.     Boolean bDone = false;
  279.     
  280.     OSErr result = noErr;
  281.     
  282.     // initialize for Carbon and QuickTime        
  283.     InitCursor();
  284.     result = EnterMovies();
  285.     BailError(result);
  286.  
  287.     // create the window
  288.     SetRect(&rectWnd, 100, 100, 200, 200);
  289.     gWindow = NewCWindow(NULL, &rectWnd, "\pVideoFrameToGworld", false, kWindowDocumentProc, (WindowPtr)-1, true, NULL);
  290.     BailNULL(gWindow);
  291.     SetPortWindowPort(gWindow);
  292.     
  293.     // get the movie
  294.     OpenMovie();
  295.     BailNULL(gMovie);
  296.     
  297.     // normalize the movie rect
  298.     GetMovieBox(gMovie, &rectMovie);
  299.     OffsetRect(&rectMovie, -rectMovie.left, -rectMovie.top);
  300.     SetMovieBox(gMovie, &rectMovie);
  301.     gMovieBox = rectMovie;
  302.     
  303.     SizeWindow(gWindow, rectMovie.right, rectMovie.bottom, true);
  304.     ShowWindow(gWindow);
  305.     
  306.     CountThemFrames();
  307.     
  308.     // create the offscreen to draw into
  309.     MakeGWorld();
  310.     BailNULL(gSrcGWorld);
  311.     
  312.     // *** set the graphics world for displaying the movie ***
  313.     SetMovieGWorld(gMovie, gSrcGWorld, GetGWorldDevice(gSrcGWorld));
  314.     
  315.     // get the first frame
  316.     NextFrame();
  317.         
  318.     while (!bDone) {
  319.         if (WaitNextEvent(everyEvent, &theEvent, 0, NULL)) {
  320.             switch (theEvent.what) {
  321.             case updateEvt:
  322.                 pWhichWindow = (WindowPtr)theEvent.message;
  323.                 if (pWhichWindow == gWindow) {
  324.                     // draw the frame
  325.                     GrafPtr savedPort;
  326.                     CGrafPtr windowPort = GetWindowPort(pWhichWindow);
  327.                     RgnHandle vizRgn = NewRgn();
  328.                     RgnHandle savedClip = NewRgn();
  329.  
  330.                     GetPort(&savedPort);
  331.                     SetPort(windowPort);
  332.                     GetClip(savedClip);
  333.                     
  334.                     BeginUpdate(pWhichWindow);
  335.                         GetPortVisibleRegion(windowPort, vizRgn);
  336.                         SetClip(vizRgn);
  337.                         BlitToScreen();
  338.                     EndUpdate(pWhichWindow);
  339.                     
  340.                     SetClip(savedClip);
  341.                     SetPort(savedPort);
  342.                     DisposeRgn(savedClip);
  343.                     DisposeRgn(vizRgn);
  344.                 }
  345.                 break;
  346.  
  347.             case mouseDown:
  348.                 nPart = FindWindow(theEvent.where, &pWhichWindow);
  349.                 if (pWhichWindow == gWindow) {
  350.                     switch (nPart) {
  351.                     case inGoAway:
  352.                         // we're done
  353.                         bDone = TrackGoAway(pWhichWindow, theEvent.where);
  354.                         break;
  355.                         
  356.                     case inContent:
  357.                         // get the next frame
  358.                         NextFrame();
  359.                         break;
  360.                                             
  361.                     case inDrag:
  362.                         BitMap screenBits;
  363.                         GetQDGlobalsScreenBits(&screenBits);
  364.                         DragWindow(pWhichWindow, theEvent.where, &screenBits.bounds);
  365.                         break;
  366.                     } // switch
  367.                 }
  368.                 break;
  369.             } // switch
  370.         }
  371.     } // while
  372.     
  373. bail:
  374.     if ( gMovie )
  375.         DisposeMovie(gMovie);
  376.         
  377.     if ( gWindow )
  378.         DisposeWindow(gWindow);
  379. }